/*
  +----------------------------------------------------------------------+
  | PHP Version 5                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2013 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt                                  |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author:                                                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "main/SAPI.h"  
#include "Zend/zend_interfaces.h"  
#include "ext/standard/php_var.h"  
#include "ext/standard/php_string.h"  
#include "ext/standard/php_smart_str.h"  
#include "ext/standard/url.h"
#include "ext/standard/php_string.h"
#include "php_wk_framework.h"
#include "wk_view.h"
#include "wk_model.h"
#include "wk_load.h"
#include "wk_controller.h"
#include "wk_input.h"
#include "wk_config.h"

zend_class_entry *wk_controller_ce;
static int le_wk_controller;

ZEND_BEGIN_ARG_INFO_EX(void_arginfo, 0, 0, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(assigns_arginfo, 0, 0, 1)  
ZEND_ARG_INFO(0, data)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(assign_arginfo, 0, 0, 2)  
ZEND_ARG_INFO(0, k)
ZEND_ARG_INFO(0, v)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(display_arginfo, 0, 0, 1)  
ZEND_ARG_INFO(0, tpl)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(setTemplateCace_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, open)
ZEND_END_ARG_INFO()

PHP_METHOD(WK_Controller, __construct){
	zval *config_obj, *load_obj, *input_obj, *instance;
	config_obj = zend_read_property(wk_controller_ce, getThis(), ZEND_STRL("config"), 0 TSRMLS_CC);
	load_obj   = zend_read_property(wk_controller_ce, getThis(), ZEND_STRL("load"), 0 TSRMLS_CC);
	input_obj  = zend_read_property(wk_controller_ce, getThis(), ZEND_STRL("input"), 0 TSRMLS_CC);

	if(Z_TYPE_P(config_obj) == IS_NULL){
		MAKE_STD_ZVAL(config_obj);
		object_init_ex(config_obj, wk_config_ce);
		zend_update_property(wk_controller_ce, getThis(), ZEND_STRL("config"), config_obj TSRMLS_CC);
	}

	if(Z_TYPE_P(input_obj) == IS_NULL){
		MAKE_STD_ZVAL(input_obj);
		object_init_ex(input_obj, wk_input_ce);
		zend_update_property(wk_controller_ce, getThis(), ZEND_STRL("input"), input_obj TSRMLS_CC);
	}
	 
	if(Z_TYPE_P(load_obj) == IS_NULL){
		MAKE_STD_ZVAL(load_obj);
		object_init_ex(load_obj, wk_load_ce);
		zend_update_property(wk_controller_ce, getThis(), ZEND_STRL("load"), load_obj TSRMLS_CC);
	}

	instance = zend_read_static_property(wk_controller_ce, ZEND_STRL("instance"), 0 TSRMLS_CC);
	if(Z_TYPE_P(instance) == IS_NULL){
		zend_update_static_property(wk_controller_ce, ZEND_STRL("instance"), getThis());
	}

	{
		zval **autoload, *apppath;
		char *routepath = get_config_path("autoload.php", 12);
		zval **libraries, **helper, **config, **language, **model;
		include(routepath);
		efree(routepath);

		if( zend_hash_find( EG(active_symbol_table), "autoload", sizeof("autoload"), (void**)&autoload) != SUCCESS){
			MAKE_STD_ZVAL(*autoload);
			ZVAL_NULL(*autoload);
		}

		get_array_item_p(Z_ARRVAL_PP(autoload), "libraries", libraries, "", 0);
		get_array_item_p(Z_ARRVAL_PP(autoload), "helper", helper, "", 0);
		get_array_item_p(Z_ARRVAL_PP(autoload), "config", config, "", 0);
		get_array_item_p(Z_ARRVAL_PP(autoload), "language", language, "", 0);
		get_array_item_p(Z_ARRVAL_PP(autoload), "model", model, "", 0);

		apppath = zend_read_static_property(wk_framework_ce, ZEND_STRL("apppath"), 0 TSRMLS_CC);

		if(Z_TYPE_PP(config) == IS_ARRAY){
			zval *config_arr;
			MAKE_STD_ZVAL(config_arr);
			array_init(config_arr);
			for(zend_hash_internal_pointer_reset(Z_ARRVAL_PP(config));
				zend_hash_has_more_elements(Z_ARRVAL_PP(config))==SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_PP(config))){
					zval **val;
					zend_hash_get_current_data(Z_ARRVAL_PP(config), (void**)&val);
					if(Z_TYPE_PP(val) == IS_STRING){
						char path[255];
						zval **tmp_config;
						php_sprintf(path, "%s/config/%s.php", Z_STRVAL_P(apppath), Z_STRVAL_PP(val));
						include(path);
						if( zend_hash_find( EG(active_symbol_table), "config", sizeof("config"), (void**)&tmp_config) == SUCCESS){
							php_array_merge(Z_ARRVAL_P(config_arr), Z_ARRVAL_PP(tmp_config), 0);
						}
					}
			}
			zend_update_property(Z_OBJCE_P(config_obj), config_obj, ZEND_STRL("config"), config_arr TSRMLS_CC);
		}

		if(Z_TYPE_PP(libraries) == IS_ARRAY){
			for(zend_hash_internal_pointer_reset(Z_ARRVAL_PP(libraries));
				zend_hash_has_more_elements(Z_ARRVAL_PP(libraries))==SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_PP(libraries))){
					zval **val;
					zend_hash_get_current_data(Z_ARRVAL_PP(libraries), (void**)&val);
					if(Z_TYPE_PP(val) == IS_STRING){
						char path[255];
						php_sprintf(path, "%s/libraries/%s_library.php", Z_STRVAL_P(apppath), Z_STRVAL_PP(val));
						include(path);
					}
			}
		}

		if(Z_TYPE_PP(helper) == IS_ARRAY){
			for(zend_hash_internal_pointer_reset(Z_ARRVAL_PP(helper));
				zend_hash_has_more_elements(Z_ARRVAL_PP(helper))==SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_PP(helper))){
					zval **val;
					zend_hash_get_current_data(Z_ARRVAL_PP(helper), (void**)&val);
					if(Z_TYPE_PP(val) == IS_STRING){
						zend_call_method_with_1_params(&load_obj, wk_load_ce, NULL, "helper", NULL, *val);
					}
			}
		}

		if(Z_TYPE_PP(model) == IS_ARRAY){
			for(zend_hash_internal_pointer_reset(Z_ARRVAL_PP(model));
				zend_hash_has_more_elements(Z_ARRVAL_PP(model))==SUCCESS;
				zend_hash_move_forward(Z_ARRVAL_PP(model))){
					zval **val;
					zend_hash_get_current_data(Z_ARRVAL_PP(model), (void**)&val);
					if(Z_TYPE_PP(val) == IS_STRING){
						zend_call_method_with_1_params(&load_obj, wk_load_ce, NULL, "model", NULL, *val);
					}
			}
		}
	}
}

/*WK_Controller::assigns(data)*/
PHP_METHOD(WK_Controller, assigns){
	zval *data, *view_obj;

	if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &data) == FAILURE ){
		RETURN_NULL();
	}

	view_obj = zend_read_static_property(wk_framework_ce, ZEND_STRL("view"), 0 TSRMLS_CC);
	zend_call_method_with_1_params(&view_obj, NULL, NULL, "assigns", &return_value, data);
}

/*WK_Controller::setTemplateCace(bool)*/
PHP_METHOD(WK_Controller, setTemplateCace){
	zval *open, *view_obj;

	if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &open) == FAILURE ){
		RETURN_NULL();
	}

	view_obj = zend_read_static_property(wk_framework_ce, ZEND_STRL("view"), 0 TSRMLS_CC);
	zend_call_method_with_1_params(&view_obj, NULL, NULL, "setOpenCache", &return_value, open);
}

/*WK_Controller::assign(key, value)*/
PHP_METHOD(WK_Controller, assign){
	zval *data, *view_obj, *name;

	if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &name, &data) == FAILURE ){
		RETURN_NULL();
	}

	view_obj = zend_read_static_property(wk_framework_ce, ZEND_STRL("view"), 0 TSRMLS_CC);
	zend_call_method_with_2_params(&view_obj, NULL, NULL, "assign", &return_value, name, data);
}

/*WK_Controller::display(tpl)*/
PHP_METHOD(WK_Controller, display){
	zval *tpl, *view_obj;

	if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &tpl) == FAILURE ){
		RETURN_NULL();
	}

	view_obj = zend_read_static_property(wk_framework_ce, ZEND_STRL("view"), 0 TSRMLS_CC);
	zend_call_method_with_1_params(&view_obj, NULL, NULL, "display", &return_value, tpl);
}

PHP_METHOD(WK_Controller, get_instance){
	return_value = zend_read_static_property(wk_controller_ce, ZEND_STRL("instance"), 0 TSRMLS_CC);
}
 
static zend_function_entry wk_controller_method[] = {
	ZEND_ME(WK_Controller, __construct, void_arginfo, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
	ZEND_ME(WK_Controller, assigns, assigns_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(WK_Controller, assign, assign_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(WK_Controller, display, display_arginfo, ZEND_ACC_PUBLIC)
	ZEND_ME(WK_Controller, get_instance, void_arginfo, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
	ZEND_ME(WK_Controller, setTemplateCace, setTemplateCace_arginfo, ZEND_ACC_PUBLIC)
	{NULL, NULL, NULL}
};

EXT_STARTUP_FUNCTION(WK_Controller){
	zend_class_entry wk_controller;
	INIT_CLASS_ENTRY(wk_controller, "WK_Controller", wk_controller_method);
	wk_controller_ce = zend_register_internal_class(&wk_controller TSRMLS_CC);

	zend_declare_property_null(wk_controller_ce, ZEND_STRL("config"), ZEND_ACC_PUBLIC TSRMLS_CC);
	zend_declare_property_null(wk_controller_ce, ZEND_STRL("input"), ZEND_ACC_PUBLIC TSRMLS_CC);
	zend_declare_property_null(wk_controller_ce, ZEND_STRL("instance"), ZEND_ACC_STATIC|ZEND_ACC_PUBLIC TSRMLS_CC);
	zend_declare_property_null(wk_controller_ce, ZEND_STRL("load"), ZEND_ACC_PUBLIC TSRMLS_CC);
	zend_declare_property_null(wk_controller_ce, ZEND_STRL("controller"), ZEND_ACC_PUBLIC TSRMLS_CC);
	zend_declare_property_null(wk_controller_ce, ZEND_STRL("module"), ZEND_ACC_PUBLIC TSRMLS_CC);
	return SUCCESS;
}